package topic

import (
	"context"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"

	"mall/common/globalkey"
	"mall/common/jwt"
	"mall/common/mqueuex"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/attachment/rpc/attachmentclient"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/forum/rpc/forumclient"
	"mall/service/user/rpc/userclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type CreateTopicLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewCreateTopicLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateTopicLogic {
	return &CreateTopicLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *CreateTopicLogic) CreateTopic(
	req *types.CreateTopicReq,
	ip string,
	headers *[]*types.Header,
) (*types.BaseIDResp, error) {
	if req.Content == nil || len(strings.TrimSpace(*req.Content)) == 0 {
		return nil, resultx.NewErrCode(resultx.FORUM_TOPIC_CONTENT_REQUIRED)
	}

	content := strings.TrimSpace(*req.Content)
	var title string
	titleRune := []rune(content)
	if len(titleRune) > 200 {
		title = string(titleRune[0:197]) + "..."
	}

	userId := jwt.GetUserId(l.ctx)
	if userId == 0 {
		return nil, resultx.NewErrCode(resultx.TOKEN_EXPIRE_ERROR)
	}

	userInfo, err := l.svcCtx.UserRpc.GetUserAuthByUserId(l.ctx, &userclient.GetUserAuthByUserIdReq{
		PlatformId: pointy.GetPointer(globalkey.ThirdPartyPlatformWechatMini),
		UserId:     pointy.GetPointer(userId),
		WithRank:   pointy.GetPointer(uint32(1)),
		WithRole:   pointy.GetPointer(uint32(1)),
	})
	if err != nil {
		logx.Infow("CreateTopic UserRpc.GetUserAuthByUserId err", logx.Field("detail", err.Error()))
		return nil, resultx.NewErrCode(resultx.USER_GET_INFO_FAILED)
	}

	if userInfo.Openid == nil {
		return nil, resultx.NewErrCode(resultx.USER_GET_INFO_FAILED)
	}

	newThumbMap := make(map[string]*types.TmpMediaInfo)
	var newMediaIds []string // 用于查询 attachmentRpc
	thumbnail := pointy.GetPointer(uint32(1))
	var newMedia []*forumclient.MediaInfo
	var newAttachmentIds []string // 用于主动通知 attachmentRpc 附件已使用
	if len(req.ImgList) > 0 {
		for idx, v := range req.ImgList {
			if v.Order == nil {
				v.Order = pointy.GetPointer(uint32(idx))
			}

			if v.Id != nil && len(*v.Id) > 0 {
				if _, ok := newThumbMap[*v.Id]; !ok { // 忽略重复id
					newThumbMap[*v.Id] = v
					newMediaIds = append(newMediaIds, *v.Id)
				}
			} else {
				newMedia = append(newMedia, &forumclient.MediaInfo{ // 第三方图片
					Uid:       v.Uid,
					Thumbnail: thumbnail,
					Order:     v.Order,
					Url:       v.Url,
					Name:      v.Name,
					MimeType:  v.MimeType,
					AltText:   v.AltText,
					MetaData:  v.MetaData,
				})
			}
		}
	}

	// 根据 newMediaIds 查询 attachments 记录到 forum_attachment_relationships
	if len(newMediaIds) > 0 {
		res, err := l.svcCtx.AttachmentRpc.BackendGetFileList(l.ctx, &attachmentclient.FileListReq{
			Ids: pointy.GetPointer(strings.Join(newMediaIds, ",")),
		})
		if err != nil {
			logx.Infow("CreateTopic AttachmentRpc.BackendGetFileList err", logx.Field("detail", err.Error()))
			return nil, err
		}

		if len(res.List) > 0 {
			for _, v := range res.List {
				if v.Id != nil && len(*v.Id) > 0 {
					mediaId := *v.Id
					if media, ok := newThumbMap[mediaId]; ok {
						var url string
						if v.Url != nil && len(*v.Url) > 0 {
							url = fmt.Sprintf("%s%s", l.svcCtx.Config.NfsConf.StaticUrl, *v.Url)
						}
						if len(url) == 0 && v.Path != nil && len(*v.Path) > 0 {
							url = fmt.Sprintf("%s%s", l.svcCtx.Config.NfsConf.ProxyUrl, *v.Path)
						}

						newMedia = append(newMedia, &forumclient.MediaInfo{
							Uid:       media.Uid,
							Id:        v.Id,
							Thumbnail: thumbnail,
							Order:     media.Order,
							Uri:       media.Url,
							Url:       pointy.GetPointer(url),
							Name:      media.Name,
							MimeType:  media.MimeType,
							AltText:   media.AltText,
							MetaData:  media.MetaData,
						})
						newAttachmentIds = append(newAttachmentIds, mediaId)
					}
				}
			}
		}
	}

	var forumId uint64
	if req.ForumId != nil && *req.ForumId >= uint64(l.svcCtx.Config.Query.DefaultForumId) {
		forumId = *req.ForumId
	} else {
		forumId = uint64(l.svcCtx.Config.Query.DefaultForumId)
	}

	var status *uint32
	if req.Draft != nil && *req.Draft > 0 {
		status = pointy.GetPointer(uint32(globalkey.StatusDraft))
	} else {
		status = pointy.GetPointer(uint32(globalkey.StatusPending))
	}

	var meta []*forumclient.MetaInfo
	if len(req.Meta) > 0 {
		for _, v := range req.Meta {
			if v.Key == nil || v.Value == nil || len(strings.TrimSpace(*v.Key)) == 0 || len(strings.TrimSpace(*v.Value)) == 0 {
				continue
			}

			meta = append(meta, &forumclient.MetaInfo{
				Key:   v.Key,
				Value: v.Value,
			})
		}
	}

	var topicId uint64
	if req.TopicId != nil && *req.TopicId > 0 {
		topicId = *req.TopicId
		_, err := l.svcCtx.ForumRpc.ReplyTopic(l.ctx, &forumclient.PostsInfo{
			TopicId:         req.TopicId,
			ForumId:         pointy.GetPointer(forumId),
			AuthorId:        userInfo.UserId,
			AuthorNickname:  userInfo.Nickname,
			AuthorAvatar:    userInfo.Avatar,
			AuthorIP:        pointy.GetPointer(ip),
			AuthorRankId:    userInfo.RankId,
			AuthorRoleId:    userInfo.RoleId,
			AuthorAnonymous: pointy.GetPointer(uint32(1)),
			PostContent:     pointy.GetPointer(content),
			Status:          status,
			Meta:            meta,
			NewMedia:        newMedia,
		})
		if err != nil {
			return nil, err
		}
	} else {
		res, err := l.svcCtx.ForumRpc.CreateTopics(l.ctx, &forumclient.TopicsInfo{
			ForumId:         pointy.GetPointer(forumId),
			AuthorId:        userInfo.UserId,
			AuthorNickname:  userInfo.Nickname,
			AuthorAvatar:    userInfo.Avatar,
			AuthorIP:        pointy.GetPointer(ip),
			AuthorRankId:    userInfo.RankId,
			AuthorRoleId:    userInfo.RoleId,
			AuthorAnonymous: pointy.GetPointer(uint32(1)),
			TopicTitle:      pointy.GetPointer(title),
			PostContent:     pointy.GetPointer(content),
			Status:          status,
			Meta:            meta,
			NewMedia:        newMedia,
		})
		if err != nil {
			return nil, err
		}

		topicId = res.Id

		userMeta := []*userclient.UserMetaInfo{{
			Key:   pointy.GetPointer(mqueuex.UserStatisticForumQuestionNew), // "_asked_question_new_status"
			Value: pointy.GetPointer("-1"),
		}}
		l.svcCtx.UserRpc.SetUserMeta(l.ctx, &userclient.SetUserMetaReq{
			UserId:   pointy.GetPointer(userId),
			MetaKey:  pointy.GetPointer(mqueuex.UserStatisticForumQuestionCount), // "_asked_question_count"
			Incr:     pointy.GetPointer(int32(1)),
			UserMeta: userMeta,
		})
	}

	if len(newAttachmentIds) > 0 {
		_, err = l.svcCtx.AttachmentRpc.CreateFileLog(l.ctx, &attachmentclient.CreateFileLogReq{
			FileIds:    newAttachmentIds,
			UserId:     pointy.GetPointer(strconv.FormatInt(int64(userId), 10)),
			Put:        pointy.GetPointer(uint32(1)),
			Thumbnail:  pointy.GetPointer(uint32(1)),
			Watermark:  pointy.GetPointer(uint32(1)),
			TermId:     pointy.GetPointer(forumId),
			ObjectId:   pointy.GetPointer(topicId),
			ObjectType: pointy.GetPointer(uint32(globalkey.AttachmentLogTypeForumTopic)),
			Title:      pointy.GetPointer("topic"),
		})
		if err != nil {
			logx.Errorw("CreateTopic AttachmentRpc.CreateFileLog err", logx.Field("detail", err.Error()))
		}
	}

	m := mqueuex.DeferredInquireAIMessage{
		UserId:  pointy.GetPointer(userId),
		TopicId: pointy.GetPointer(topicId),
	}
	body, err := json.Marshal(m)
	if err != nil {
		logx.Errorw("CreateTopic createDeferredInquireAITask json.Marshal error", logx.Field("detail", err.Error()))
		// return nil, err
	} else {
		err = l.svcCtx.KqDeferredInquireAIClient.Push(string(body))
		if err != nil {
			logx.Errorw("CreateTopic createDeferredInquireAITask error", logx.Field("detail", err.Error()))
			// return nil, err
		}
	}

	return &types.BaseIDResp{
		Id:  topicId,
		Msg: "回答生成中...",
	}, nil
}
